#define _MINE_DLL_API_	_declspec(dllexport)
#include "ABSKnotInsert.h"
#include "..\Research2.0\cu\CUDADataStruct.h"


#include "cuda.h"
#include "builtin_types.h"
#include "vector_functions.h"
#include "cuda_d3d9_interop.h"
#include "cuda_runtime_api.h"
#include "cutil.h"


bool KICreatedSurf = false;
bool KICreatedRender = false;
bool MCKICreated = false;
bool isPeel=true;
bool needShadow = false;
bool morfReAllocated = false;


#ifdef _MANAGED
#pragma managed(push, off)
#endif

extern "C"
{
	void KICreateMC(GAS_SURF* pGAS, int width, int height);
	void KICreateAS(GAS_SURF* pGAS);

	void KICreateABSCUDA(bool IsAS, float* pFuncData, int* index, int* indexInverse, int nPatch, int deg[3], int seg[3], float* box[3]);
	void KICreateRenderCUDA(RENDER_PARAM* renderParam);
	void KICleanABSCUDA();
	void KICleanRenderCUDA();
	void KICleanMC();

	//void KIKernel(RENDER_PARAM* renderParam, unsigned char* surface, size_t pitch, bool IsAS);
	void KIMCOne(RENDER_PARAM* renderParam, unsigned char* surIn, unsigned char* surNorm, unsigned char* surPos, size_t pitch, bool* reNormal);
	void KIOneKer(RENDER_PARAM* renderParam, unsigned char* surNorm, unsigned char* surPos, size_t pitch, bool* reNormal);
	void KIABSKer(RENDER_PARAM* renderParam, unsigned char* surNorm, unsigned char* surPos, size_t pitch, bool* reNormal);
	void KIABSPeel(RENDER_PARAM* renderParam, unsigned char* surNorm, unsigned char* surPos, size_t pitch, bool* reNormal);
	void KIABSPeelMorf(RENDER_PARAM* renderParam, unsigned char* surNorm, unsigned char* surPos, size_t pitch, bool* rNormal, float* MorfData, int dataSize);
	void KIABSPeelShadow(RENDER_PARAM* renderParam, unsigned char* surNorm, unsigned char* surPos, size_t pitch, bool* reNormal);
}

BOOL APIENTRY DllMain( HMODULE hModule,
					  DWORD  ul_reason_for_call,
					  LPVOID lpReserved
					  )
{
	return TRUE;
}

void KIABS(ABSSf* pABS, RENDER_PARAM* renderParam, unsigned char* surIn, unsigned char* surNorm, unsigned char* surPos, size_t pitch, bool IsAS, GAS_SURF* pGAS, bool* reNormal, float* MorfData)
{
	//GetGroundPlane(groundPlane, corner, line, renderParam->invViewProj);
	//GetGroundPlane2(groundPlane2, renderParam->invViewProj);


	if (NULL==pABS&&IsAS==false)	return;
	if (pABS&&!pABS->m_ABez)		pABS->ABS2ABez();
	
	if (surIn&&!MCKICreated)
	{
		KICreateMC(pGAS, renderParam->renderWidth, renderParam->renderHeight);
		MCKICreated = true;
	}
	if(!surIn&&!KICreatedSurf)
	{
		if(IsAS)		KICreateAS(pGAS);
		else			KICreateABSCUDA(IsAS, pABS->GetCompactFuncData(), pABS->GetCompactIndex(), pABS->GetCompactInverseInd(), pABS->GetActualPatchNum(), pABS->m_ABez->deg, pABS->m_ABez->seg, pABS->m_ABez->box);
		KICreateRenderCUDA(renderParam);
		KICreatedRender = true;
		KICreatedSurf = true;
	}

	if(MorfData)
	{
		if(!morfReAllocated)			
		{
			KICleanABSCUDA();
			KICreateABSCUDA(IsAS, pABS->GetCompactFuncData(), pABS->GetCompactIndex(), pABS->GetCompactInverseInd(), pABS->GetActualPatchNum(), pABS->m_ABez->deg, pABS->m_ABez->seg, /*box*/pABS->m_ABez->box);
			if(!KICreatedRender)	{KICreateRenderCUDA(renderParam);KICreatedRender = true;}
			morfReAllocated=true;
		}
		KIABSPeelMorf(renderParam, surNorm, surPos, pitch, reNormal, MorfData, pABS->GetActualPatchNum()*pABS->m_degSize);
	}else

	if (surIn)			
		KIMCOne(renderParam, surIn, surNorm, surPos, pitch, reNormal);
	else 
	if(IsAS)			KIOneKer(renderParam, surNorm, surPos, pitch, reNormal);
	else 
		if (isPeel)		
			if(needShadow)
				KIABSPeelShadow(renderParam, surNorm, surPos, pitch, reNormal);
			else
				KIABSPeel(renderParam, surNorm, surPos, pitch, reNormal);
		else			KIABSKer(renderParam, surNorm, surPos, pitch, reNormal);
	cudaThreadSynchronize();
}

void KICleanABS()
{
	if (KICreatedSurf)
	{
		KICleanABSCUDA();
		KICleanRenderCUDA();
		KICreatedSurf = false;
	}
	if (MCKICreated)
	{
		KICleanMC();
		MCKICreated = false;
	}
}

